#include "napi/native_api.h"
#include <stdio.h>
#include <vector>
#include <queue>
#include <limits>
#include <utility>
#include <algorithm>
#include <cctype>
#include <string>
#include <sstream>

static napi_value PrintA(napi_env env, napi_callback_info info)
{
    printf("a\n");

    napi_value result;
    napi_create_string_utf8(env, "a", 1, &result);
    return result;
}

static napi_value DijkstraAlgorithm(napi_env env, napi_callback_info info)
{
    // 获取参数
    size_t argc = 3;
    napi_value args[3] = {nullptr};
    napi_get_cb_info(env, info, &argc, args, nullptr, nullptr);
    
    // 检查参数数量
    if (argc != 3) {
        napi_throw_error(env, nullptr, "需要三个参数: 邻接矩阵、顶点数和起始顶点");
        return nullptr;
    }
    
    // 检查参数类型
    bool isArray;
    napi_is_array(env, args[0], &isArray);
    if (!isArray) {
        napi_throw_type_error(env, nullptr, "第一个参数必须是邻接矩阵数组");
        return nullptr;
    }
    
    // 获取顶点数
    uint32_t vertexCount;
    napi_get_value_uint32(env, args[1], &vertexCount);
    
    // 获取起始顶点
    uint32_t startVertex;
    napi_get_value_uint32(env, args[2], &startVertex);
    
    if (startVertex >= vertexCount) {
        napi_throw_range_error(env, nullptr, "起始顶点必须小于顶点总数");
        return nullptr;
    }
    
    // 获取邻接矩阵
    std::vector<std::vector<int>> graph(vertexCount, std::vector<int>(vertexCount, 0));
    uint32_t arrayLength;
    napi_get_array_length(env, args[0], &arrayLength);
    
    if (arrayLength != vertexCount) {
        napi_throw_error(env, nullptr, "邻接矩阵行数必须等于顶点数");
        return nullptr;
    }
    
    // 解析邻接矩阵
    for (uint32_t i = 0; i < vertexCount; i++) {
        napi_value row;
        napi_get_element(env, args[0], i, &row);
        
        bool isRowArray;
        napi_is_array(env, row, &isRowArray);
        if (!isRowArray) {
            napi_throw_type_error(env, nullptr, "邻接矩阵的每一行必须是数组");
            return nullptr;
        }
        
        uint32_t rowLength;
        napi_get_array_length(env, row, &rowLength);
        
        if (rowLength != vertexCount) {
            napi_throw_error(env, nullptr, "邻接矩阵的每一行长度必须等于顶点数");
            return nullptr;
        }
        
        for (uint32_t j = 0; j < vertexCount; j++) {
            napi_value element;
            napi_get_element(env, row, j, &element);
            
            int value;
            napi_get_value_int32(env, element, &value);
            graph[i][j] = value;
        }
    }
    
    // 执行Dijkstra算法
    const int INF = std::numeric_limits<int>::max();
    std::vector<int> dist(vertexCount, INF);
    std::vector<bool> visited(vertexCount, false);
    std::vector<int> prev(vertexCount, -1);
    
    dist[startVertex] = 0;
    
    // 使用优先队列优化
    std::priority_queue<std::pair<int, int>, std::vector<std::pair<int, int>>, std::greater<std::pair<int, int>>> pq;
    pq.push({0, startVertex});
    
    while (!pq.empty()) {
        int u = pq.top().second;
        pq.pop();
        
        if (visited[u]) continue;
        visited[u] = true;
        
        for (int v = 0; v < vertexCount; v++) {
            // 如果有边且未访问过
            if (graph[u][v] > 0) {
                int weight = graph[u][v];
                if (dist[u] + weight < dist[v]) {
                    dist[v] = dist[u] + weight;
                    prev[v] = u;
                    pq.push({dist[v], v});
                }
            }
        }
    }
    
    // 创建结果对象
    napi_value result, distances, paths;
    napi_create_object(env, &result);
    napi_create_array(env, &distances);
    napi_create_array(env, &paths);
    
    // 填充距离数组
    for (uint32_t i = 0; i < vertexCount; i++) {
        napi_value distValue;
        if (dist[i] == INF) {
            napi_create_int32(env, -1, &distValue); // -1表示不可达
        } else {
            napi_create_int32(env, dist[i], &distValue);
        }
        napi_set_element(env, distances, i, distValue);
    }
    
    // 填充路径数组
    for (uint32_t i = 0; i < vertexCount; i++) {
        napi_value path;
        napi_create_array(env, &path);
        
        if (i != startVertex && dist[i] != INF) {
            std::vector<int> pathVec;
            int current = i;
            while (current != -1) {
                pathVec.push_back(current);
                current = prev[current];
            }
            std::reverse(pathVec.begin(), pathVec.end());
            
            for (uint32_t j = 0; j < pathVec.size(); j++) {
                napi_value vertex;
                napi_create_int32(env, pathVec[j], &vertex);
                napi_set_element(env, path, j, vertex);
            }
        } else if (i == startVertex) {
            // 起点到自己的路径就是自己
            napi_value vertex;
            napi_create_int32(env, startVertex, &vertex);
            napi_set_element(env, path, 0, vertex);
        }
        
        napi_set_element(env, paths, i, path);
    }
    
    // 设置结果对象的属性
    napi_set_named_property(env, result, "distances", distances);
    napi_set_named_property(env, result, "paths", paths);
    
    return result;
}

static napi_value AddSo(napi_env env, napi_callback_info info)
{
    size_t argc = 2;
    napi_value args[2] = {nullptr};

    napi_get_cb_info(env, info, &argc, args , nullptr, nullptr);

    napi_valuetype valuetype0;
    napi_typeof(env, args[0], &valuetype0);

    napi_valuetype valuetype1;
    napi_typeof(env, args[1], &valuetype1);

    double value0;
    napi_get_value_double(env, args[0], &value0);

    double value1;
    napi_get_value_double(env, args[1], &value1);

    napi_value sum;
    napi_create_double(env, value0 + value1, &sum);

    return sum;

}

static napi_value ForLoop(napi_env env, napi_callback_info info)
{
    // 获取参数
    size_t argc = 3;
    napi_value args[3] = {nullptr};
    napi_get_cb_info(env, info, &argc, args, nullptr, nullptr);
    
    // 检查参数数量
    if (argc != 3) {
        napi_throw_error(env, nullptr, "需要三个参数: 起始值、结束值和步长");
        return nullptr;
    }
    
    // 获取起始值
    int32_t start;
    napi_get_value_int32(env, args[0], &start);
    
    // 获取结束值
    int32_t end;
    napi_get_value_int32(env, args[1], &end);
    
    // 获取步长
    int32_t step;
    napi_get_value_int32(env, args[2], &step);
    
    // 检查步长是否为0
    if (step == 0) {
        napi_throw_error(env, nullptr, "步长不能为0");
        return nullptr;
    }
    
    // 创建结果数组
    std::vector<int32_t> result;
    
    // 执行for循环
    if (step > 0) {
        // 正向循环
        for (int32_t i = start; i < end; i += step) {
            result.push_back(i);
        }
    } else {
        // 反向循环
        for (int32_t i = start; i > end; i += step) {
            result.push_back(i);
        }
    }
    
    // 创建JavaScript数组
    napi_value jsArray;
    napi_create_array(env, &jsArray);
    
    // 填充数组
    for (size_t i = 0; i < result.size(); i++) {
        napi_value value;
        napi_create_int32(env, result[i], &value);
        napi_set_element(env, jsArray, i, value);
    }
    
    return jsArray;
}

static napi_value WhileLoop(napi_env env, napi_callback_info info)
{
    // 获取参数
    size_t argc = 3;
    napi_value args[3] = {nullptr};
    napi_get_cb_info(env, info, &argc, args, nullptr, nullptr);
    
    // 检查参数数量
    if (argc != 3) {
        napi_throw_error(env, nullptr, "需要三个参数: 初始值、条件值和步长");
        return nullptr;
    }
    
    // 获取初始值
    int32_t initial;
    napi_get_value_int32(env, args[0], &initial);
    
    // 获取条件值
    int32_t condition;
    napi_get_value_int32(env, args[1], &condition);
    
    // 获取步长
    int32_t step;
    napi_get_value_int32(env, args[2], &step);
    
    // 检查步长是否为0
    if (step == 0) {
        napi_throw_error(env, nullptr, "步长不能为0");
        return nullptr;
    }
    
    // 创建结果数组
    std::vector<int32_t> result;
    
    // 执行while循环
    int32_t current = initial;
    if (step > 0) {
        // 正向循环 (当current < condition时继续)
        while (current < condition) {
            result.push_back(current);
            current += step;
        }
    } else {
        // 反向循环 (当current > condition时继续)
        while (current > condition) {
            result.push_back(current);
            current += step; // 注意这里是加上负数步长，相当于减法
        }
    }
    
    // 创建JavaScript数组
    napi_value jsArray;
    napi_create_array(env, &jsArray);
    
    // 填充数组
    for (size_t i = 0; i < result.size(); i++) {
        napi_value value;
        napi_create_int32(env, result[i], &value);
        napi_set_element(env, jsArray, i, value);
    }
    
    return jsArray;
}

static napi_value TrimString(napi_env env, napi_callback_info info)
{
    // 获取参数
    size_t argc = 2;
    napi_value args[2] = {nullptr};
    napi_get_cb_info(env, info, &argc, args, nullptr, nullptr);
    
    // 检查参数数量
    if (argc < 1) {
        napi_throw_error(env, nullptr, "需要至少一个参数: 要处理的字符串");
        return nullptr;
    }
    
    // 检查第一个参数是否为字符串
    napi_valuetype valuetype0;
    napi_typeof(env, args[0], &valuetype0);
    if (valuetype0 != napi_string) {
        napi_throw_type_error(env, nullptr, "第一个参数必须是字符串");
        return nullptr;
    }
    
    // 获取字符串长度
    size_t str_length;
    napi_get_value_string_utf8(env, args[0], nullptr, 0, &str_length);
    
    // 分配内存并获取字符串内容
    std::string input_str(str_length + 1, '\0');
    napi_get_value_string_utf8(env, args[0], &input_str[0], str_length + 1, nullptr);
    
    // 获取第二个参数（修剪模式），默认为"all"
    std::string trim_mode = "all";
    if (argc > 1) {
        napi_valuetype valuetype1;
        napi_typeof(env, args[1], &valuetype1);
        if (valuetype1 == napi_string) {
            size_t mode_length;
            napi_get_value_string_utf8(env, args[1], nullptr, 0, &mode_length);
            std::string temp_mode(mode_length + 1, '\0');
            napi_get_value_string_utf8(env, args[1], &temp_mode[0], mode_length + 1, nullptr);
            trim_mode = temp_mode;
        }
    }
    
    // 根据不同模式处理字符串
    std::string result = input_str;
    
    if (trim_mode == "left" || trim_mode == "start") {
        // 去除左侧空格
        result.erase(result.begin(), std::find_if(result.begin(), result.end(), [](unsigned char ch) {
            return !std::isspace(ch);
        }));
    } else if (trim_mode == "right" || trim_mode == "end") {
        // 去除右侧空格
        result.erase(std::find_if(result.rbegin(), result.rend(), [](unsigned char ch) {
            return !std::isspace(ch);
        }).base(), result.end());
    } else if (trim_mode == "all" || trim_mode == "both") {
        // 去除两侧空格
        result.erase(result.begin(), std::find_if(result.begin(), result.end(), [](unsigned char ch) {
            return !std::isspace(ch);
        }));
        result.erase(std::find_if(result.rbegin(), result.rend(), [](unsigned char ch) {
            return !std::isspace(ch);
        }).base(), result.end());
    } else if (trim_mode == "all_spaces") {
        // 去除所有空格
        result.erase(std::remove_if(result.begin(), result.end(), [](unsigned char ch) {
            return std::isspace(ch);
        }), result.end());
    }
    
    // 创建返回值
    napi_value return_value;
    napi_create_string_utf8(env, result.c_str(), NAPI_AUTO_LENGTH, &return_value);
    
    return return_value;
}

static napi_value AddSpaceEveryThreeChars(napi_env env, napi_callback_info info)
{
    // 获取参数
    size_t argc = 1;
    napi_value args[1] = {nullptr};
    napi_get_cb_info(env, info, &argc, args, nullptr, nullptr);
    
    // 检查参数数量
    if (argc < 1) {
        napi_throw_error(env, nullptr, "需要一个参数: 要处理的字符串");
        return nullptr;
    }
    
    // 检查参数是否为字符串
    napi_valuetype valuetype0;
    napi_typeof(env, args[0], &valuetype0);
    if (valuetype0 != napi_string) {
        napi_throw_type_error(env, nullptr, "参数必须是字符串");
        return nullptr;
    }
    
    // 获取字符串长度
    size_t str_length;
    napi_get_value_string_utf8(env, args[0], nullptr, 0, &str_length);
    
    // 分配内存并获取字符串内容
    std::string input_str(str_length + 1, '\0');
    napi_get_value_string_utf8(env, args[0], &input_str[0], str_length + 1, nullptr);
    
    // 处理字符串，每三个字符后添加一个空格
    std::stringstream result;
    for (size_t i = 0; i < input_str.length(); ++i) {
        result << input_str[i];
        // 每三个字符后添加一个空格，但不在字符串末尾添加
        if ((i + 1) % 3 == 0 && i < input_str.length() - 1) {
            result << ' ';
        }
    }
    
    // 创建返回值
    std::string result_str = result.str();
    napi_value return_value;
    napi_create_string_utf8(env, result_str.c_str(), NAPI_AUTO_LENGTH, &return_value);
    
    return return_value;
}
static napi_value ToUpperCase(napi_env env, napi_callback_info info)
{
    size_t argc = 1;
    napi_value args[1] = {nullptr};

    napi_get_cb_info(env, info, &argc, args, nullptr, nullptr);

    // 检查参数类型是否为字符串
    napi_valuetype valuetype;
    napi_typeof(env, args[0], &valuetype);
    if (valuetype != napi_string) {
        napi_throw_type_error(env, nullptr, "String expected");
        napi_value result;
        napi_create_string_utf8(env, "", NAPI_AUTO_LENGTH, &result);
        return result;
    }

    // 获取字符串长度
    size_t str_length;
    napi_get_value_string_utf8(env, args[0], nullptr, 0, &str_length);

    // 分配内存并获取字符串内容
    char* buffer = new char[str_length + 1];
    size_t copied_length;
    napi_get_value_string_utf8(env, args[0], buffer, str_length + 1, &copied_length);
    buffer[str_length] = '\0';

    // 将字符串转换为大写
    std::string input_str(buffer);
    std::string result_str = input_str;
    for (size_t i = 0; i < result_str.length(); i++) {
        if (std::islower(result_str[i])) {
            result_str[i] = std::toupper(result_str[i]);
        }
    }
    delete[] buffer;

    // 创建返回值
    napi_value result;
    napi_create_string_utf8(env, result_str.c_str(), NAPI_AUTO_LENGTH, &result);

    return result;
}

static napi_value CountCharacters(napi_env env, napi_callback_info info)
{
    size_t argc = 1;
    napi_value args[1] = {nullptr};

    napi_get_cb_info(env, info, &argc, args, nullptr, nullptr);

    // 检查参数类型是否为字符串
    napi_valuetype valuetype;
    napi_typeof(env, args[0], &valuetype);
    if (valuetype != napi_string) {
        napi_throw_type_error(env, nullptr, "String expected");
        napi_value result;
        napi_create_int32(env, -1, &result);
        return result;
    }

    // 获取字符串长度
    size_t str_length;
    napi_get_value_string_utf8(env, args[0], nullptr, 0, &str_length);

    // 分配内存并获取字符串内容
    char* buffer = new char[str_length + 1];
    size_t copied_length;
    napi_get_value_string_utf8(env, args[0], buffer, str_length + 1, &copied_length);
    buffer[str_length] = '\0';

    // 统计字符数量
    std::string input_str(buffer);
    delete[] buffer;

    // 创建返回值
    napi_value result;
    napi_create_int32(env, static_cast<int32_t>(input_str.length()), &result);

    return result;
}

static napi_value PrintB(napi_env env, napi_callback_info info)
{
    printf("b\n");
    
    napi_value result;
    napi_create_string_utf8(env, "b", 1, &result);
    return result;
}

static napi_value PrintC(napi_env env, napi_callback_info info)
{
    printf("c\n");
    
    napi_value result;
    napi_create_string_utf8(env, "c", 1, &result);
    return result;
}

EXTERN_C_START
static napi_value Init(napi_env env, napi_value exports) {
    napi_property_descriptor desc[] = {
        {"add", nullptr, AddSo, nullptr, nullptr, nullptr, napi_default, nullptr},
        {"printA", nullptr, PrintA, nullptr, nullptr, nullptr, napi_default, nullptr },
        { "dijkstra", nullptr, DijkstraAlgorithm, nullptr, nullptr, nullptr, napi_default, nullptr },
        { "forLoop", nullptr, ForLoop, nullptr, nullptr, nullptr, napi_default, nullptr },
        { "whileLoop", nullptr, WhileLoop, nullptr, nullptr, nullptr, napi_default, nullptr },
        { "trim", nullptr, TrimString, nullptr, nullptr, nullptr, napi_default, nullptr },
        { "addSpaceEveryThreeChars", nullptr, AddSpaceEveryThreeChars, nullptr, nullptr, nullptr, napi_default, nullptr },
        { "toUpperCase", nullptr, ToUpperCase, nullptr, nullptr, nullptr, napi_default, nullptr },
        { "countCharacters", nullptr, CountCharacters, nullptr, nullptr, nullptr, napi_default, nullptr },
        { "printB", nullptr, PrintB, nullptr, nullptr, nullptr, napi_default, nullptr },
        { "printC", nullptr, PrintC, nullptr, nullptr, nullptr, napi_default, nullptr }
    };
    napi_define_properties(env, exports, sizeof(desc) / sizeof(desc[0]), desc);
    return exports;
}
EXTERN_C_END

static napi_module demoModule = {
    .nm_version = 1,
    .nm_flags = 0,
    .nm_filename = nullptr,
    .nm_register_func = Init,
    .nm_modname = "add",
    .nm_priv = ((void*)0),
    .reserved = { 0 },
};

extern "C" __attribute__((constructor)) void RegisterAddModule(void)
{
    napi_module_register(&demoModule);
}
